#include "ground.h"
unsigned short GetPatchPointIndexInTerrainTileSpace(
	int xPatchIndex, int zPatchIndex,
	int xPointIndex, int zPointIndex) {
	// xPatchIndex = 0, zPatchIndex = 0, xPointIndex -> 0~4 ,zPointIndex-> 0~4
	// xPatchPointIndexInTerrainTiled -> 0~4
	// zPatchPointIndexInTerrainTiled -> 0~4

	// xPatchIndex = 1, zPatchIndex = 1, xPointIndex -> 0~4 ,zPointIndex-> 0~4
	// xPatchPointIndexInTerrainTiled -> 4~8
	// zPatchPointIndexInTerrainTiled -> 4~8
	int xPatchPointIndexInTerrainTiled = xPointIndex + xPatchIndex * 4;
	int zPatchPointIndexInTerrainTiled = zPointIndex + zPatchIndex * 4;
	return xPatchPointIndexInTerrainTiled + zPatchPointIndexInTerrainTiled * 81;
}
void Patch::Init(float xOffset, float zOffset) {
	mCurrentLODLevel = 0;
	//mVertexBuffer = new VertexBuffer;
	//mVertexBuffer->SetSize(25);
	mIBO = 0;
	mPosition.x = xOffset;
	mPosition.y = 0.0f;
	mPosition.z = zOffset;
	//for (int z = 0; z < 5; ++z) {
	//	float zPosition = zOffset + 2.0f - z;
	//	for (int x = 0; x < 5; ++x) {
	//		float xPosition = -2.0f + x + xOffset;
	//		int point_index = x + z * 5;
	//		mVertexBuffer->SetPosition(point_index, xPosition, 0.0f, zPosition);
	//		mVertexBuffer->SetNormal(point_index, 0.0f, 1.0f, 0.0f);
	//	}
	//}
}
void Patch::Draw(Shader* shader) {
	mVertexBuffer->Bind();
	glEnableVertexAttribArray(shader->mPositionLocation);
	glVertexAttribPointer(shader->mPositionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
	glEnableVertexAttribArray(shader->mColorLocation);
	glVertexAttribPointer(shader->mColorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 4));
	glEnableVertexAttribArray(shader->mTexcoordLocation);
	glVertexAttribPointer(shader->mTexcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 8));
	glEnableVertexAttribArray(shader->mNormalLocation);
	glVertexAttribPointer(shader->mNormalLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 12));
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
	glDrawElements(GL_TRIANGLES,
		mCurrentLODLevelIndexCount,
		GL_UNSIGNED_SHORT, 
		0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	mVertexBuffer->Unbind();
}
int Patch::UpdateIndexBuffer(unsigned short* indices, int offset,
	int xPathcIndex, int zPatchIndex,
	int LeftLODLevel, int RightLODLevel, int TopLODLevel, int BottomLODLevel) {
	if (mCurrentLODLevel == 0) {
		int index_count = 0;
		int index_offset = offset;
		int patch_point_indices_in_terrain_tile_space[25];
		for (int z=0;z<5;z++){
			for (int x=0;x<5;x++){
				int patch_point_index = x + 5 * z;
				patch_point_indices_in_terrain_tile_space[patch_point_index] =
					GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, x, z);
			}
		}
		//middle rect
		{
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[12];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[12];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[12];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[12];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[12];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[12];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			index_count += 24;
		}
		if (LeftLODLevel == 2) {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[0];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];
			index_count += 9;
		}
		else if (LeftLODLevel == 1) {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[0];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[10];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[10];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[10];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[10];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];
			index_count += 12;
		}
		else {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[0];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[5];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[5];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[10];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[10];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[10];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[15];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[15];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[11];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[15];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];
			index_count += 18;
		}
		if (RightLODLevel == 2) {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[24];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];
			index_count += 9;
		}
		else if (RightLODLevel == 1) {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[14];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[14];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[14];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[14];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[24];
			index_count += 12;
		}
		else {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[9];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[9];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[9];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[14];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[13];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[14];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[14];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[19];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[19];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[24];
			index_count += 18;
		}
		if (TopLODLevel == 2) {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[24];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];
			index_count += 9;
		}
		else if (TopLODLevel == 1) {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[22];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[22];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[22];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[22];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[24];
			index_count += 12;
		}
		else {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[20];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[21];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[16];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[21];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[21];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[22];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[17];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[22];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[22];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[23];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[18];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[24];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[23];
			index_count += 18;
		}
		if (BottomLODLevel == 2) {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[0];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			index_count += 9;
		}
		else if (BottomLODLevel == 1) {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[0];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[2];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[2];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[2];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[2];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			index_count += 12;
		}
		else {
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[0];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[1];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[1];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[2];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[6];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[2];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[2];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[3];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[7];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[3];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];

			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[3];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[4];
			indices[index_offset++] = patch_point_indices_in_terrain_tile_space[8];
			index_count += 18;
		}
		return index_count;
	}
	else if (mCurrentLODLevel == 1) {
		int index_offset = offset;
		int index_count = 0;
		//generate left part
		if (LeftLODLevel == 2) {
			index_count += 3;
			indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 0);
			indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 2);
			indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 4);
		}
		else {
			index_count += 6;
			int _0_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 0);
			int _1_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 2);
			int _2_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 4);
			int _3_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 2);
			indices[index_offset++] = _0_index;
			indices[index_offset++] = _1_index;
			indices[index_offset++] = _3_index;

			indices[index_offset++] = _3_index;
			indices[index_offset++] = _1_index;
			indices[index_offset++] = _2_index;
		}
		//generate right part
		if (RightLODLevel == 2) {
			index_count += 3;
			int _0_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 0);
			int _1_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 4);
			int _2_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 2);
			indices[index_offset++] = _0_index;
			indices[index_offset++] = _1_index;
			indices[index_offset++] = _2_index;
		}
		else {
			index_count += 6;
			int _0_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 0);
			int _1_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 4);
			int _2_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 2);
			int _3_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 2);
			indices[index_offset++] = _0_index;
			indices[index_offset++] = _3_index;
			indices[index_offset++] = _2_index;

			indices[index_offset++] = _2_index;
			indices[index_offset++] = _3_index;
			indices[index_offset++] = _1_index;
		}
		//generate top part
		if (TopLODLevel == 2) {
			index_count += 3;
			int _0_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 2);
			int _1_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 4);
			int _2_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 4);
			indices[index_offset++] = _0_index;
			indices[index_offset++] = _1_index;
			indices[index_offset++] = _2_index;
		}
		else {
			index_count += 6;
			int _0_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 2);
			int _1_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 4);
			int _2_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 4);
			int _3_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 4);
			indices[index_offset++] = _0_index;
			indices[index_offset++] = _1_index;
			indices[index_offset++] = _3_index;

			indices[index_offset++] = _0_index;
			indices[index_offset++] = _3_index;
			indices[index_offset++] = _2_index;
		}
		//generate bottom part
		if (BottomLODLevel == 2) {
			index_count += 3;
			int _0_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 2);
			int _1_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 0);
			int _2_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 0);
			indices[index_offset++] = _0_index;
			indices[index_offset++] = _1_index;
			indices[index_offset++] = _2_index;
		}
		else {
			index_count += 6;
			int _0_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 2);
			int _1_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 0);
			int _2_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 0);
			int _3_index = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 2, 0);
			indices[index_offset++] = _0_index;
			indices[index_offset++] = _1_index;
			indices[index_offset++] = _3_index;

			indices[index_offset++] = _0_index;
			indices[index_offset++] = _3_index;
			indices[index_offset++] = _2_index;
		}
		return index_count;
	}
	else if (mCurrentLODLevel == 2) {
		int index_offset = offset;
		indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex,zPatchIndex,0,0);
		indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 0);
		indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 4);

		indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 0, 4);
		indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 0);
		indices[index_offset++] = GetPatchPointIndexInTerrainTileSpace(xPathcIndex, zPatchIndex, 4, 4);
		return 6;
	}
	return 0;
}
int Ground::GetPatchLODLevel(int current_patch_x_index, int current_patch_z_index, 
	int offset_x, int offset_z) {
	int patch_index = (current_patch_x_index + current_patch_z_index * 20);
	int current_patch_lod_level = mPatches[patch_index].mCurrentLODLevel;
	if (offset_x==-1){
		if (current_patch_x_index==0){
			return current_patch_lod_level;
		}
		else {
			int left_patch_index = (current_patch_x_index-1 + current_patch_z_index * 20);
			return mPatches[left_patch_index].mCurrentLODLevel;
		}
	}else if (offset_x==1){
		if (current_patch_x_index == 19) {
			return current_patch_lod_level;
		}
		else {
			int right_patch_index = (current_patch_x_index + 1 + current_patch_z_index * 20);
			return mPatches[right_patch_index].mCurrentLODLevel;
		}
	}else{
		if (offset_z == 1) {
			if (current_patch_z_index == 19) {
				return current_patch_lod_level;
			}
			else {
				int top_patch_index = (current_patch_x_index + (current_patch_z_index+1) * 20);
				return mPatches[top_patch_index].mCurrentLODLevel;
			}
		}
		else if (offset_z == -1) {
			if (current_patch_z_index == 0) {
				return current_patch_lod_level;
			}
			else {
				int bottom_patch_index = (current_patch_x_index + (current_patch_z_index - 1 ) * 20);
				return mPatches[bottom_patch_index].mCurrentLODLevel;
			}
		}
	}
	return 2;
}
void Ground::Update(glm::vec3 camera_pos) {
	for (int z = 0; z < 20; ++z) {
		for (int x = 0; x < 20; ++x) {
			int patch_index = (x + z * 20);
			float distance_from_camera = glm::distance(mPatches[patch_index].mPosition, camera_pos);
			if (distance_from_camera < 20.0f) {
				mPatches[patch_index].mCurrentLODLevel = 0;
			}
			else if (distance_from_camera < 100.0f) {
				mPatches[patch_index].mCurrentLODLevel = 1;
			}
			else if (distance_from_camera < 200.0f) {
				mPatches[patch_index].mCurrentLODLevel = 2;
			}
		}
	}
	//calculate patch index buffer
	unsigned short indices[65535] = { 0 };
	mCurrentIndexCount = 0;
	for (int z = 0; z < 20; ++z) {
		for (int x = 0; x < 20; ++x) {
			int patch_index = (x + z * 20);
			int left_patch_lod_level = GetPatchLODLevel(x, z, -1, 0);
			int right_patch_lod_level = GetPatchLODLevel(x, z, 1, 0);
			int top_patch_lod_level = GetPatchLODLevel(x, z, 0, 1);
			int bottom_patch_lod_level = GetPatchLODLevel(x, z, 0, -1);

			int current_patch_index_count = mPatches[patch_index].UpdateIndexBuffer(
				indices, mCurrentIndexCount, x, z,
				left_patch_lod_level, right_patch_lod_level, 
				top_patch_lod_level, bottom_patch_lod_level);
			mCurrentIndexCount += current_patch_index_count;
		}
	}
	if (mIBO != 0) {
		glDeleteBuffers(1, &mIBO);
	}
	mIBO = CreateBufferObject(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * mCurrentIndexCount, GL_STATIC_DRAW, indices);
}
void Ground::Init() {
	mIBO = 0;
	mVertexBuffer = new VertexBuffer;
	mVertexBuffer->SetSize(6561);
	mPatches = new Patch[400];//400 x 16 x 6 = 400 x 96 = 38400 -> index < 65535 unsigned short [ES2.0]
	for (int zPatchIndex = 0; zPatchIndex < 20; ++zPatchIndex) {
		float zCenterPosition = 40.0f - 2.0f - zPatchIndex * 4.0f;
		for (int xPatchIndex = 0; xPatchIndex < 20; ++xPatchIndex) {
			float xCenterPosition = xPatchIndex * 4.0f - 40.0f + 2.0f;
			int patch_index = (xPatchIndex + zPatchIndex * 20);
			mPatches[patch_index].Init(xCenterPosition,zCenterPosition);

			int xDirectionPatchPointStartIndex = 1;
			if (xPatchIndex==0){//5 points
				xDirectionPatchPointStartIndex = 0;
			}
			int zDirectionPatchPointStartIndex = 1;
			if (zPatchIndex == 0) {
				zDirectionPatchPointStartIndex = 0;
			}
			//generate patch points
			for (int z = zDirectionPatchPointStartIndex; z < 5; ++z) {
				float zPosition = zCenterPosition + 2.0f - z;
				for (int x = xDirectionPatchPointStartIndex; x < 5; ++x) {
					float xPosition = -2.0f + x + xCenterPosition;
					//zPatchIndex = 0,xPatchIndex = 0 , x -> 0~4 
					//xPatchPointIndexInTerrainTiled -> 0~4
					//zPatchIndex = 0,xPatchIndex = 1 , x -> 1~4 
					//xPatchPointIndexInTerrainTiled -> 4 + 1~4 : 5 -> 8
					//zPatchIndex = 0,xPatchIndex = 19 , x -> 1~4 
					//xPatchPointIndexInTerrainTiled -> 19*4(76) + 1~4 : 77 -> 80
					int point_index = GetPatchPointIndexInTerrainTileSpace(xPatchIndex,zPatchIndex,x,z);
					mVertexBuffer->SetPosition(point_index, xPosition, float(rand())/float(RAND_MAX), zPosition);
					mVertexBuffer->SetNormal(point_index, 0.0f, 1.0f, 0.0f);
				}
			}
		}
	}
	mShader = new Shader;
	mShader->Init("Res/ground.vs", "Res/ground.fs");
	mShader->SetVec4("U_LightPos", 0.0f, 0.0f, 1.0f, 0.0f);
	mShader->SetVec4("U_LightAmbient", 1.0f, 1.0f, 1.0f, 1.0f);
	mShader->SetVec4("U_LightDiffuse", 1.0f, 1.0f, 1.0f, 1.0f);
	mShader->SetVec4("U_LightOpt", 32.0f, 0.0f, 0.0f, 1.0f);
	mShader->SetVec4("U_AmbientMaterial", 0.1f, 0.1f, 0.1f, 1.0f);
	mShader->SetVec4("U_DiffuseMaterial", 0.1f, 0.4f, 0.6f, 1.0f);
}
void Ground::Draw(glm::mat4 & viewMatrix, glm::mat4 & projectionMatrix) {
	glEnable(GL_DEPTH_TEST);
	mVertexBuffer->Bind();
	mShader->Bind(glm::value_ptr(mModelMatrix), glm::value_ptr(viewMatrix), glm::value_ptr(projectionMatrix));
	glEnableVertexAttribArray(mShader->mPositionLocation);
	glVertexAttribPointer(mShader->mPositionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
	glEnableVertexAttribArray(mShader->mColorLocation);
	glVertexAttribPointer(mShader->mColorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 4));
	glEnableVertexAttribArray(mShader->mTexcoordLocation);
	glVertexAttribPointer(mShader->mTexcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 8));
	glEnableVertexAttribArray(mShader->mNormalLocation);
	glVertexAttribPointer(mShader->mNormalLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 12));
	
	//glDrawArrays(GL_POINTS, 0, mVertexBuffer->mVertexCount);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
	glDrawElements(GL_TRIANGLES, mCurrentIndexCount, GL_UNSIGNED_SHORT, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	mVertexBuffer->Unbind();
}